package org.paradac;

public class DivideAndConquer<T> {
	private static int corePoolSize = 4;
	private static int maximumPoolSize = corePoolSize * 2;

	private Node<T> rootNode = new Node<T>();
	private INodeProcessor<T> nodeProcessor;

	public DivideAndConquer(T rootData, INodeProcessor<T> nodeProcessor) {
		super();
		this.nodeProcessor = nodeProcessor;
		this.rootNode.data = rootData;
		this.rootNode.level = 0;
	}

	public class DividerFunction<E> implements Function<Node<E>> {
		private INodeProcessor<E> nodeProcessor;
		private DCThreadPoolExecutor executor;

		public DividerFunction(INodeProcessor<E> nodeProcessor, 
		    DCThreadPoolExecutor executor) {
			super();
			this.nodeProcessor = nodeProcessor;
			this.executor = executor;
		}

		@Override
		public void apply(Node<E> a) {
			a.children = nodeProcessor.divider(a.data);
			for (int i = 0; i < a.children.size(); i++) {
				Node<E> ch = new Node<E>();
				ch.data = a.children.get(i);
				ch.level = a.level - 1;
				ch.parent = a;
				if (!nodeProcessor.isLeaf(ch.data)) {
					ch.f = this;
					executor.execute(ch);
				}
			}
			a.processedChildrenCount.set(a.children.size());
		}
	}

	public void divide() {
		DCThreadPoolExecutor executor = new DCThreadPoolExecutor(corePoolSize,
		    maximumPoolSize);
		DividerFunction<T> dividerFunction = new DividerFunction<T>(nodeProcessor, executor);
		rootNode.f = dividerFunction;
		executor.execute(rootNode);
		executor.run();
	}


}
